package org.si.icon;

import java.awt.*;
import org.si.graphics.BackgroundPaintProvider;
import org.si.graphics.ForegroundPaintProvider;
import org.si.graphics.PaintProvider;
import org.si.utils.ScalePolicy;

/**
 * A simple icon instance that can be used as a placeholder for prototyping or demos. The icon is fairly simple but
 * provides edge markers and orientation information for help when testing.
 *
 * @author Matt Nathan
 */
public class PlaceholderIcon extends AbstractScalableIcon {

    private final int width;
    private final int height;
    private final PaintProvider foreground;
    private final PaintProvider background;
    private final ScalePolicy scalePolicy;





    /**
     * Create a new placeholder icon with the given default size and that will fill the available area with the
     * components background and foreground.
     *
     * @param width  The default width of the icon.
     * @param height The default height of the icon.
     */
    public PlaceholderIcon(int width, int height) {
        this(width, height, null);
    }





    /**
     * Create a new placeholder icon with the given default size and scale policy. This icon will use the components
     * foreground and background for its painting.
     *
     * @param width       The default width of the icon.
     * @param height      The default height of the icon.
     * @param scalePolicy The scaling policy for the icon.
     */
    public PlaceholderIcon(int width, int height, ScalePolicy scalePolicy) {
        this(width, height, new ForegroundPaintProvider(), new BackgroundPaintProvider(), scalePolicy);
    }





    /**
     * Create a new placeholder icon with the given defualt size and that uses the given PaintProviders for it's
     * background and foreground. Note that if the PaintProvider is null or returns null then that part of the icon will
     * not get painted.
     *
     * @param width      The default width for the icon.
     * @param height     The default height for the icon.
     * @param foreground The forground paint provider.
     * @param background The background paint provider.
     */
    public PlaceholderIcon(int width, int height,
                           PaintProvider foreground, PaintProvider background) {
        this(width, height, foreground, background, null);
    }





    /**
     * Create a new PlaceholderIcon with the given fields. If either if the PaintProvider variable are null then the
     * corresponding layer of the icon will not get painted. If scalePolicy is null then a default {@link
     * ScalePolicy#BOTH} instance will be used.
     *
     * @param width       The default width for the icon.
     * @param height      The default height for the icon.
     * @param foreground  The forground paint provider.
     * @param background  The background paint provider.
     * @param scalePolicy The scale policy for this icon.
     */
    public PlaceholderIcon(int width, int height,
                           PaintProvider foreground, PaintProvider background,
                           ScalePolicy scalePolicy) {
        if (scalePolicy == null) {
            scalePolicy = ScalePolicy.BOTH;
        }
        this.width = width;
        this.height = height;
        this.foreground = foreground;
        this.background = background;
        this.scalePolicy = scalePolicy;
    }





    @Override
    public void fitInto(Component c, int width, int height, Dimension result) {
        scalePolicy.fitInto(new Dimension(getIconWidth(), getIconHeight()),
                            new Dimension(width, height),
                            result);
    }





    @Override
    public void paintIcon(Component c, Graphics g, int x, int y, int width, int height) {
        Graphics2D g2 = (Graphics2D) g.create();
        if (background != null) {
            Paint p = background.get(c, x, y, width, height);
            if (p != null) {
                g2.setPaint(p);
                g2.fillRect(x, y, width, height);
            }
        }
        if (foreground != null) {
            Paint p = foreground.get(c, x, y, width, height);
            if (p != null) {
                g2.setPaint(p);

                int centerx = x + width / 2;
                int centery = y + height / 2;

                // draw border
                g2.drawRect(x, y, width - 1, height - 1);

                // draw cross across the area
                g2.drawLine(x, y, x + width - 1, y + height - 1);
                g2.drawLine(x, y + height - 1, x + width - 1, y);

                // draw arrows pointing to the edges
                int pointerSize = 4;
                // top
                for (int i = 0; i < pointerSize; i++) {
                    g2.drawLine(centerx - i, y + i, centerx + i, y + i);
                }
                // bottom
                for (int i = 0; i < pointerSize; i++) {
                    g2.drawLine(centerx - i, y + height - 1 - i, centerx + i, y + height - 1 - i);
                }
                // left
                for (int i = 0; i < pointerSize; i++) {
                    g2.drawLine(x + i, centery - i, x + i, centery + i);
                }
                // right
                for (int i = 0; i < pointerSize; i++) {
                    g2.drawLine(x + width - 1 - i, centery - i, x + width - 1 - i, centery + i);
                }

                // draw up line
                g2.drawLine(centerx, y, centerx, centery);

            }
        }
        g2.dispose();
    }





    @Override
    public int getIconWidth() {
        return width;
    }





    @Override
    public int getIconHeight() {
        return height;
    }
}
